<template>
  <h2>列表渲染</h2>
  <div class="note">
    <p>1. v-for：基于一个数组来渲染一个列表</p>
    <p>2. v-for: 可以在定义 v-for 变量别名时使用解构 (解构对象时必须写内部存在属性)</p>
    <p>3. v-for: 可以遍历数组，数组嵌套对象，对象等</p>
    <p>4. v-for：可以接收一个整数值/范围值（注意初值是从1开始）</p>
    <p>5. v-for: template 标签上也可以使用 v-for 来渲染一个包含多个元素的块</p>
    <hr />
    <p>1. 语法1：v-for="(value, index) in items" 建议:key, 严格代码模式</p>
    <p>2. 语法2：v-for="value of items" 更接近JS的迭代器语法</p>
    <p>3. 语法3：可接收三个参数：v-for="(value,key,index) in myObject 顺序不能反</p>
    <hr />
    <p>1. 同时使用 v-if 和 v-for 不推荐，二者的优先级不明显</p>
    <p>
      2. 同时存在于一个节点上时，v-if 比 v-for 的优先级更高。这意味着 v-if 的条件将无法访问到
      v-for作用域内定义的变量别名
    </p>
    <p>
      3. eslinet语法拒绝同时使用这两个指令，先包装一层 'template'标签 再在其上使用 v-for
      可以解决这个问题
    </p>
    <hr />
    <p>
      1. 可以直接在组件上MyComponent标签上使用
      v-for，但是，这不会自动将任何数据传递给组件，因为组件有自己独立的作用域。
    </p>
    <p>2. 为了将迭代后的数据传递到组件中，我们还需要传递 props：</p>
    <hr />
    <p>1. Vue 能够侦听响应式数组的变更方法，并在它们被调用时触发相关的更新。</p>
    <p>2. 修改原数组：push()、pop()、shift()、unshift()、splice()、sort()、reverse()</p>
    <p>3. 返回新数组：filter()，concat() 和 slice()等</p>
    <p>
      4.
      使用会修改原数组的方法时记得用扩展运算符创建一个副本，避免原数组更改。如[...numbers].reverse()
    </p>
  </div>

  <hr class="hr-style" />
  <h3>v-for 的基本语法</h3>
  <div class="test">
    <ul>
      <h4>普通数组遍历</h4>
      <li v-for="(item, index) in items" :key="index">数组键值：{{ index }} - {{ item }}</li>
      <li v-for="(item, index) in items2" :key="index">数组嵌套对象：{{ index }} - {{ item }}</li>
      <h4>解构数组遍历</h4>
      <li v-for="([value], index) in items" :key="index">
        数组嵌套对象：{{ index }} - {{ value }}
      </li>
      <li v-for="({ message }, index) in items2" :key="index">
        数组嵌套对象：{{ index }} - {{ message }}
      </li>
      <h4>使用v-for_of遍历</h4>
      <li v-for="({ message }, index) of items2" :key="index">
        数组嵌套对象：{{ index }} - {{ message }}
      </li>
    </ul>
  </div>

  <hr class="hr-style" />
  <h3>v-for 与对象</h3>
  <div class="test">
    <ul>
      <h4>key-value</h4>
      <li v-for="(value, key) in myObject" :key="key">{{ key }}:{{ value }}</li>
      <h4>index-key-value</h4>
      <li v-for="(value, key, index) in myObject" :key="key">{{ index }}:{{ key }}:{{ value }}</li>
    </ul>
  </div>

  <hr class="hr-style" />
  <h3>v-for 里使用范围值</h3>
  <div class="test">
    <span v-for="(n, key) in 10" :key>{{ n }}</span>
  </div>

  <hr class="hr-style" />
  <h3>v-for VS v-if</h3>
  <div class="test">
    <ul>
      <!-- <li v-for="(value,key) in myObject" :key v-if = 'myObject.isTrue'></li> -->
      <p style="font-weight: bold">
        eslintvue/no-use-v-if-with-v-for 在eslint语法中规定v-if与v-for不能同时使用
      </p>
      <p style="font-weight: bold">先包装一层 'template'标签 再在其上使用 v-for 可以解决这个问题</p>
      <template v-for="(value, key) in myObject" :key>
        <li v-if="myObject.isTrue">
          {{ myObject.author }}
        </li>
      </template>
    </ul>
  </div>

  <hr class="hr-style" />
  <h3>组件上使用 v-for???????????????????????</h3>
  <div class="test">
    在组件上直接写 v-for 不会自动将任何数据传递给组件:
    <MyComponent v-for="(value, key) in 3" :key />

    
      <!-- 需要传递 props,才能将迭代后的数据传递到组件中：
      <MyComponent
      v-for="(value,key,index) in myObject" 
      :value = 'value'
      :key = 'key'
      :index="index" 
      />  -->
   
  </div>

  <hr class="hr-style" />
  <h3>数组变化侦测</h3>
  <div class="test">
    <p style="font-weight: bold">
      单层嵌套的v-for循环如（[1, 2, 3, 4, 5]）可直接用计算属性进行计算
    </p>
    <li v-for="(n, key) in evenNumbers" :key>{{ n }}</li>
    <p style="font-weight: bold">
      多层嵌套的v-for循环如（[[1, 2, 3, 4, 5],[6, 7, 8, 9,
      10]]）计算属性不可行，可直接定义一个计算函数
    </p>
    <ul v-for="(numbers, key) in sets" :key>
      <li v-for="(n, key) in even(numbers)" :key>{{ n }}</li>
    </ul>
    <p style="font-weight: bold">
      在计算属性中使用reverse() 和 sort()等之前应创建一个原数组的副本，否则会影响到原数组
    </p>
    <p style="color: pink; font-weight: bold">创建副本：</p>
    <li v-for="(n, key) in [...numbers].reverse()" :key>{{ n }}</li>
    <li>{{ numbers }}</li>
    <p style="color: pink; font-weight: bold">未创建副本：</p>
    <li v-for="(n, key) in numbers.reverse()" :key>{{ n }}</li>
    <li>{{ numbers }}</li>
  </div>
</template>

<script lang="ts">
export default {
  name: 'Study3StuDemo5'
}
</script>

<script setup lang="ts">
import { ref, reactive, computed } from 'vue'

import MyComponent from './components/MyComponent.vue'
// 数据
const items = ref(['apple', 'banana', 'orange'])
const items2 = ref([{ message: 'Foo' }, { message: 'Bar' }])

const myObject = reactive({
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10',
  isTrue: true
})

const numbers = ref([1, 2, 3, 4, 5])
const evenNumbers = computed(() => {
  return numbers.value.filter((n) => n % 2 == 0)
})

const sets = ref([
  [1, 2, 3, 4, 5],
  [6, 7, 8, 9, 10]
])
// const evenNumbers2 = computed(() => {    这里的n是二维数组，无法遍历，需要定义一个函数
//   return sets.value.filter((n: number[]) => n % 2 == 0)
// })
function even(numbers: number[]) {
  return numbers.filter((number: number) => number % 2 == 0)
}
</script>

<style scoped>
body {
  padding: 20px;
}
h2 {
  color: red;
}
h3 {
  color: rgb(220, 85, 85);
}
h4 {
  color: skyblue;
}
pre {
  background-color: #92e2a7;
}
.hr-style {
  border: 3px solid gold;
  margin: 20px 0;
}
.note {
  margin: 10px;
  padding: 10px;
  border: 3px solid rgb(221, 121, 202);
}
.note p {
  color: rgb(226, 106, 204);
  font-weight: bold;
}
</style>
